﻿using System.Threading.Tasks;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;
using ImpromptuInterface;
using System.Collections.Generic;
using System.Linq;
using System;
using LunchLearn.WebApi.Infrastructure.Notifications;

namespace LunchLearn.WebApi.Hubs
{
    [HubName("order")]
    public class OrderHub : Hub
    {
        private readonly INotificationBridge _messageBridge;
        private static Dictionary<Guid, List<string>> _viewUsers;

        public OrderHub(INotificationBridge messageBridge)
        {
            _viewUsers = new Dictionary<Guid, List<string>>();
            _messageBridge = messageBridge;
            _messageBridge.MessageReceived += (s, e) => ProcessMessage(e);
        }

        public Task ConnectToOrderView(Guid orderId)
        {
            if (!_viewUsers.ContainsKey(orderId))
            {
                _viewUsers.Add(orderId, new List<string>());
            }
            if (_viewUsers[orderId].All(x => x != Context.ConnectionId))
            {
                _viewUsers[orderId].Add(Context.ConnectionId);
                return Groups.Add(Context.ConnectionId, orderId.ToString()).ContinueWith(t => SendViewersNotification(orderId));
            }
            return null;
        }

        private Task SendViewersNotification(Guid orderId)
        {
            if (_viewUsers.ContainsKey(orderId))
            {
                var message = string.Format("{0} viewing this order", _viewUsers[orderId].Count());
                return Clients.Group(orderId.ToString()).usersOnline(message);
            }
            throw new Exception("Order not found in notification engine");
        }

        public Task DisconnectToOrderView(Guid orderId)
        {
            if (_viewUsers.ContainsKey(orderId))
            {
                if (_viewUsers[orderId].Any(x => x == Context.ConnectionId))
                {
                    _viewUsers[orderId].Remove(Context.ConnectionId);
                }
                return Groups.Remove(Context.ConnectionId, orderId.ToString()).ContinueWith(t => SendViewersNotification(orderId)).ContinueWith(t => Clients.Caller.removeMessage());
            }
            return null;
        }

        public override Task OnConnected()
        {
            return base.OnConnected().ContinueWith(t => Clients.All.newUserConnected("New user connected."));
        }

        public override Task OnDisconnected()
        {
            var viewUsers = _viewUsers.FirstOrDefault(x => x.Value.Any(y => y == Context.ConnectionId));
            if (viewUsers.Value != null)
            {
                viewUsers.Value.Remove(Context.ConnectionId);
            }
            if (viewUsers.Key != Guid.Empty)
            {
                Groups.Remove(Context.ConnectionId, viewUsers.Key.ToString());
                return base.OnDisconnected().ContinueWith(t => SendViewersNotification(viewUsers.Key));
            }
            return null;
        }


        private void ProcessMessage(NotificationBridgeEventArgs e)
        {
            Impromptu.InvokeMember(Clients.All, e.Notification.DynamicMethod, e.Notification);
        }

    }
}